 

import { StationNetwork } from "GameLoop/Path/StationNetwork";
import { ATeamCombat } from "GameLoop/WorldState/EntityManager/Entitys";
import { Math2D } from "algorithm/Math2d";
import { PositionHelper } from "utils/position/PositionHelper";
import { UtilsHelper } from "utils/position/UtilsHelper";
 

export class TeamUtils
{
/**
     * 已经接近目标
     * @param targetVec 
     * @returns 
     */
    public static isNearTarget(targetVec:IFVector2)
    {
        return Math2D.distance(targetVec)<2
    }
    public static isSqareMoveable(team:ATeamCombat, dir:DirectionConstant ):1|2|false
    {
        const poss = _.map(team.creeps,e=>e.pos);
        const code  = TeamUtils.IsPositionsMoveable(poss,dir);
        if(code === OK)
        {
           return 2
        }
        else if(code ===2)
        {
           return 1
        }
        return false
    }
    /**
     *
     * @param poss
     * @param direction
     * @returns OK是平地 2 有沼泽 false 不能走 true 被建筑或者爬挡住
     */
    static   IsPositionsMoveable(poss:RoomPosition[],direction:DirectionConstant ):OK|boolean|2
    {

        let nextTeamPos =   _.map(poss,e=> UtilsHelper.GetDirectionPos(e,direction))  ;
        for(const e of nextTeamPos)
        {
            if(Game.rooms[e.roomName]?.isBlock(e))
            {
                // 这个位置已经被预定了不能走动
                return false;
            }
        }
        let nextCheckPos = nextTeamPos.filter(e=>!poss.find(c=>c.isEqualTo(e)));
        global.Log.Info(`检查坐标 ${JSON.stringify(nextCheckPos)}`);
        let hassweep = false;
        for(const item of nextCheckPos)
        {
            const terrain =  Game.map.getRoomTerrain(item.roomName);
            if(terrain.get(item.x,item.y) == TERRAIN_MASK_WALL)
            {
                // 墙

                for(const e of nextCheckPos)
                {
                    Game.rooms[poss[0].roomName].visual?.circle(e.x,e.y);
                }
                return false;
            }
            else
            {
                if(terrain.get(item.x,item.y) == TERRAIN_MASK_SWAMP)
                {
                    hassweep = true;
                }
                if(!this.IsPosMoveAble(item))
                {
                        // 被建筑挡住了

                    for(const e of nextCheckPos)
                    {
                        Game.rooms[poss[0].roomName].visual?.circle(e.x,e.y);
                    }
                    return true;
                }
                if(this.IsPosExistCreep(item))
                {
                    // 被爬挡住
                    return true;
                }
            }
        }
        if(hassweep)
        {
            return 2
        }
        return OK;
    }

    private static   IsPosMoveAble(nextPos:RoomPosition)
    {
           const findstructure = PositionHelper.lookFor(LOOK_STRUCTURES, nextPos );

           const cachecontroller = Game.rooms[nextPos.roomName]?.controller;
           if(cachecontroller && cachecontroller.my)
           {
                const bolckStructures = _.filter(findstructure,item=>( item.structureType != STRUCTURE_ROAD&& item.structureType != STRUCTURE_CONTAINER && item.structureType != STRUCTURE_RAMPART))
                return bolckStructures.length ==0;
           }
           else
           {
                const bolckStructures = _.filter(findstructure,item=>(item.structureType != STRUCTURE_ROAD&& item.structureType != STRUCTURE_CONTAINER ))
                return bolckStructures.length ==0;
           }

    }

    static findBlockStructure(nextPos:RoomPosition)
    {
           const findstructure =  PositionHelper.lookFor(LOOK_STRUCTURES,nextPos );

           const cachecontroller = Game.rooms[nextPos.roomName]?.controller;
           if(cachecontroller && cachecontroller.my)
           {
                const bolckStructures = _.filter(findstructure,item=>( item.structureType != STRUCTURE_ROAD&& item.structureType != STRUCTURE_CONTAINER && item.structureType != STRUCTURE_RAMPART))
                return bolckStructures;
           }
           else
           {
                const bolckStructures = _.filter(findstructure,item=>(item.structureType != STRUCTURE_ROAD&& item.structureType != STRUCTURE_CONTAINER ))
                return bolckStructures;
           }

    }

    static findBlockCreep(nextPos:RoomPosition)
    {
        // 不是我自己的爬才会挡住。是我自己的爬也会挡住
        const findcreeps = PositionHelper.lookFor(LOOK_CREEPS,nextPos);
        return findcreeps
    }

    static IsPosExistCreep(nextPos:RoomPosition)
    {
        // 不是我自己的爬才会挡住。是我自己的爬也会挡住
        const findcreeps = PositionHelper.lookFor(LOOK_CREEPS,nextPos);
        return findcreeps.length>0
    }

    static IsPositionMoveAble(nextPos:RoomPosition):true|false|0
    {
        const terrain =  Game.map.getRoomTerrain(nextPos.roomName);
        if(terrain.get(nextPos.x,nextPos.y) == TERRAIN_MASK_WALL)
        {
              // 墙

              return false;
        }
        else
        {
              if(!this.IsPosMoveAble(nextPos))
              {
                    // 被建筑挡住了

                    return false;
              }
              if(this.IsPosExistCreep(nextPos))
              {
                  // 被爬挡住
                  return 0;
              }
              return true;
        }
    }

    static ArmyPositions(LeaderPos:RoomPosition,offsets:IFVector2[])
    {
        return offsets.map(e=>PositionHelper.addPosition( LeaderPos,e))
    }


    static GetArmyRange(leaderpos:RoomPosition,area:number)
    {
        // 以leaderpos为左上角，向右下角扩展4的范围
        let xmin = leaderpos.x - area;
        let ymin = leaderpos.y - area;
        let xmax = leaderpos.x + area+1;
        let ymax = leaderpos.y + area+1;
        if(xmin<0)
        {
            xmin = 0;
        }
        if(ymin<0)
        {
            ymin = 0;
        }
        if(xmax>49)
        {
            xmax = 49;
        }
        if(ymax>49)
        {
            ymax = 49;
        }
        return {xmin,ymin,xmax,ymax}
    }
    public static IsFromExitToExit(curpos:RoomPosition,nextDirection:DirectionConstant): boolean
    {
        return UtilsHelper.isAcrossRoom(curpos,nextDirection);

    }


    public  static GetExpectPostionMap(creepspos:RoomPosition[]):{[key:string]:number}
    {
        const formatpos = (x:number,y:number)=>
        {
            return `${x}_${y}`
        }
        // 提高效率只算xy不算roomname
        const GetProbabilityPos = (pos: RoomPosition) =>
        {
            if( pos.x==0 || pos.x==49)
            {
                return [ formatpos(0,pos.y),formatpos(49,pos.y)]
            }

            if( pos.y==0 || pos.y==49)
            {
                return [formatpos(pos.x,0),formatpos(pos.x,49)]
            }
            return  [formatpos(pos.x,pos.y)]
        }
        const map:{[key:string]:number}={};
        for(const pos of creepspos)
        {
            const  ProbabilityPos = GetProbabilityPos(pos);
            for(const item of ProbabilityPos)
            {
            map[item]=1;
            }
        }
        return map
    }

    /**
     * 用于在指定房间寻找集合点
     * @param startpos 起点坐标
     * @param offsets 小队相对偏移量
     * @returns
     */
    public static findAssemble(startpos:RoomPosition,offsets:IFVector2[])
    {
        const visltpos=[startpos];
        const visitpos = new Set<string>();
        const visitrecord = {};
        let assemblepos:RoomPosition[] | undefined;
        while(!assemblepos && visltpos.length>0)
        {
            assemblepos = this.assemble(visltpos,offsets,visitpos,visitrecord);
        }
        return assemblepos
    }
    private static assemble(NextVisits:RoomPosition[],offsets:IFVector2[],VisitPoints:Set<string>,VisitList:Record<string,boolean>)
    {
        // 集合
        let nextpos:RoomPosition[]=[];
        for(const startPos of NextVisits)
        {
            const formatkey = `${startPos.roomName}_${startPos.x}_${startPos.y}`;
            VisitPoints.add(formatkey);
            const checkPositions = _.map(offsets,item=>PositionHelper.Add(startPos,item.x,item.y));
            let findAssemble = true;
            for(const item of checkPositions)
            {
                if(!item || !this.isStandable(item,VisitList))
                {
                    findAssemble = false;
                }

            }
            if(findAssemble)
            {

                return checkPositions  as RoomPosition[]
            }
            nextpos = nextpos.concat( this.getNextVisits(startPos,VisitPoints));
        }
        NextVisits.splice(0,NextVisits.length);
        NextVisits.push(...nextpos);
        return undefined
    }
    private static isStandable(Pos:RoomPosition,VisitList:Record<string,boolean>):boolean
    {
        const formatkey = `${Pos.roomName}_${Pos.x}_${Pos.y}`;
        if(Pos.x<=0 ||Pos.y<=0 ||Pos.x>=49 ||Pos.y>=49 )
        {
            VisitList[formatkey]=false;
            return false;
        }
        if(Game.rooms[Pos.roomName].isBlock(Pos))
        {
            VisitList[formatkey]=false;
            return VisitList[formatkey];
        }
        if(VisitList[formatkey] !== undefined)
        {
            return VisitList[formatkey];
        }

        const terrain = Game.map.getRoomTerrain(Pos.roomName);

        if(terrain.get(Pos.x,Pos.y) == TERRAIN_MASK_WALL)
        {
            VisitList[formatkey] = false;
            return VisitList[formatkey] ;
        }
        const structureMatrix = StationNetwork.getInstance.PathFinder.getRoomMatrix(Pos.roomName);
        // 要
        if(structureMatrix)
        {
            // 自己的房间要排除spawn模块的两个container
            // const coreentity = this.getEntity(entity_type.spawn);
            // if(coreentity)
            // {
            //     if(Pos.x>=coreentity.Base.x && coreentity.Base)
            //     coreentity.Base
            // }
            if(this.isValidAssembleRange(Pos))
            {
                VisitList[formatkey] = structureMatrix.get(Pos.x,Pos.y) ==0;
            }
            else
            {
                VisitList[formatkey]  = false;
            }

        }
        else
        {
            const structures = Pos.lookFor(LOOK_STRUCTURES).filter(item=>item.structureType!= STRUCTURE_ROAD && item.structureType!=STRUCTURE_CONTAINER);
            const creeps = Pos.lookMyCreep();
            VisitList[formatkey] = (structures.length == 0 && !creeps)
        }
        return VisitList[formatkey];
    }

    private static  isValidAssembleRange(Pos:RoomPosition)
    {
        const cache = global.world.PollBlueplan(Pos.roomName);
        if(cache )
        {
            const basepos = cache.getModulePlan("SpawnEntity")[0].pos;
            if(Pos.x>=basepos.x && Pos.y>=basepos.y && Pos.x<=basepos.x+6 &&Pos.y<=basepos.y+6)
            {
                return false;
            }
            if(Pos.x<=0 ||Pos.y<=0 ||Pos.x>=49 ||Pos.x>=49 )
            {
                return false;
            }
            return true;
        }
         
        return true;
    }

    private static getNextVisits(pos:RoomPosition,VisitList:Set<string>)
    {
        // 要排除掉container
        const dirs :DirectionConstant[]=[LEFT,RIGHT,TOP,BOTTOM];
        const nextpos:{
            roomName: string;
            x: number;
            y: number;
        }[]=[];
        for(const item of dirs)
        {
            const newpos = UtilsHelper.directionToPos(pos,item);

            if(newpos)
            {
                const formatkey = `${newpos.roomName}_${newpos.x}_${newpos.y}`;
                if(!VisitList.has(formatkey))
                {
                    nextpos.push(newpos)
                }
            }
        }
        return nextpos as RoomPosition[];
    }
    /**
     * 判断爬是否可移动
     * @param creep 
     * @param direct 
     * @returns 
     */
    public static isCreepMoveable(creep:Creep,direct:DirectionConstant|0):OK|ERR_TIRED|ERR_NOT_FOUND
    {
        // 1.不是从出口到出口
        // 2.疲劳为0
        if(creep.fatigue>0)
        {
            return ERR_TIRED;
        }

        if(direct && TeamUtils.IsFromExitToExit(creep.pos,direct))
        {
            return ERR_NOT_FOUND;
        }
        return OK;
    }
}
